﻿#include "FITKAcousticsVTKGraphObjectFEFaces.h"
#include "FITKAcousticsVTKSharedDataManager.h"
#include "FITKAcousticsVTKGraphActor.h"

#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEFace.h"
#include "FITK_Interface/FITKVTKAlgorithm/FITKGraphActor.h"

#include <vtkMultiBlockDataSet.h>
#include <vtkExtractBlock.h>
#include <vtkDataSet.h>
#include <vtkProperty.h>
#include <vtkCompositeDataGeometryFilter.h>
#include <vtkLookupTable.h>
#include <vtkMapper.h>
#include <vtkCellData.h>

namespace Exchange
{
    FITKAcousticsVTKGraphObjectFEFaces::FITKAcousticsVTKGraphObjectFEFaces(Acoustics::FITKAcousticsFEModel * feModel) :
        FITKAcousticsVTKGraphObjectMergedData(feModel)
    {
        if (!feModel){
            return;
        }

        //数据初始化
        init();

        //数据连接
        if (!generateDataSet()){
            return;
        }

        //初始化演员
        generateGraph();
        //更新可见性
        updateVisibility();
        //渲染类型初始化
        m_graphInfo.Type = FITKAcousticsVTKCommons::FEFaceGraph;
    }

    void FITKAcousticsVTKGraphObjectFEFaces::updateById(int dataId, bool forceUpdate)
    {
        //判断当前数据是否存在
        int dataIndex = -1;
        vtkDataSet* dataSet = FITKAcousticsVTKSharedDataManager::GetInstance()->getFEFacesDataSet(dataId, dataIndex);
        Q_UNUSED(dataIndex);

        //如果数据不存在或需要强制刷新
        if (dataSet == nullptr || forceUpdate == true) {
            //更新数据
            FITKAcousticsVTKSharedDataManager::GetInstance()->updateFEFaceDataSet(dataId);
        }
        else {
            //更新颜色
            FITKAcousticsVTKSharedDataManager::GetInstance()->updateFEFaceDataSetColor(dataId);
        }
    }

    void FITKAcousticsVTKGraphObjectFEFaces::updateByDataColor()
    {
        if (!m_fActor){
            return;
        }

        vtkLookupTable* lookupTable = getActorLut(m_fActor);
        if (lookupTable == nullptr)return;

        // Enable the cell data color array.
        m_fActor->setScalarVisibility(true);
        m_fActor->setScalarModeToUseCellFieldData();
        m_fActor->selectScalarArray(DATA_COLOR_ARRAY_NAME);

        // Update the look up table.
        lookupTable->SetVectorModeToRGBColors();
        lookupTable->Build();

        // Reset the transparent.
        m_fActor->GetProperty()->SetOpacity(1.);

        // Update the pipeline.
        if (m_comp2Poly){
            m_comp2Poly->Modified();
        }
    }

    bool FITKAcousticsVTKGraphObjectFEFaces::getDataVisibility()
    {
        // Get the runtime settings for visibility. 
        bool showSubSys = getRuntimeSettingAs<bool>(RTS_KEY_VISIBLE_SUB_SYSTEMS, true);
        bool showFE = getRuntimeSettingAs<bool>(RTS_KEY_VISIBLE_FE, true);
        bool showFEFaces = getRuntimeSettingAs<bool>(RTS_KEY_VISIBLE_FE_SURFACE, true);
        bool isShow = showFE && showSubSys && showFEFaces;
        return isShow;
    }

    void FITKAcousticsVTKGraphObjectFEFaces::updateVisibility()
    {
        Acoustics::FITKAcousticsFEModel* feMode = dynamic_cast<Acoustics::FITKAcousticsFEModel*>(_dataObj);
        if (feMode == nullptr)return;
        Acoustics::FITKAcousticsFEFaceManager* feFaceManager = feMode->getFEFaceManager();
        if (feFaceManager == nullptr)return;

        int index = 0;
        if (m_extractBlock && m_multiBlockDataSet)
        {
            //清空
            m_multiBlockDataSet->ReleaseData();
            m_extractBlock->RemoveAllIndices();

            for (int i = 0; i < feFaceManager->getDataCount();i++) {
                Acoustics::FITKAcousticsFEFace* feFace = feFaceManager->getDataByIndex(i);
                if (!feFace) {
                    continue;
                }

                // Check the data visibility.
                if (!feFace->isEnable()) {
                    continue;
                }

                int dataIndex = -1;
                vtkDataSet* dataSet = FITKAcousticsVTKSharedDataManager::GetInstance()->getFEFacesDataSet(feFace->getDataObjectID(), dataIndex);
                if (dataIndex < 0 || dataSet == nullptr) {
                    continue;
                }

                updateById(feFace->getDataObjectID(), false);

                m_multiBlockDataSet->SetBlock(index, dataSet);
                m_extractBlock->AddIndex(index);
                index++;
            }
        }

        // Update the whole object's visibility.
        this->Superclass::updateVisibility();
    }

    int FITKAcousticsVTKGraphObjectFEFaces::getShapeIdByVTKCellId(int vtkId, FITKAcousticsVTKCommons::ShapeMeshAbsEnum topAbsShapeType)
    {
        if (!m_fActor){
            return -1;
        }

        // Get the input dataset.
        vtkMapper* mapper = m_fActor->GetMapper();
        if (!mapper){
            return -1;
        }

        vtkDataSet* dataSet = mapper->GetInputAsDataSet();
        if (!dataSet){
            return -1;
        }

        vtkCellData* cellData = dataSet->GetCellData();
        if (!cellData){
            return -1;
        }

        switch (topAbsShapeType)
        {
        case Exchange::FITKAcousticsVTKCommons::STA_FACE:
        {
            // Get the id array.
            vtkIntArray* idArray = vtkIntArray::SafeDownCast(cellData->GetArray(DATA_SUB_ID_ARRAY_NAME));
            if (!idArray){
                return -1;
            }

            int nVal = idArray->GetNumberOfValues();
            if (vtkId >= nVal){
                return -1;
            }

            int dataId = idArray->GetValue(vtkId);
            return dataId;
        }
        case Exchange::FITKAcousticsVTKCommons::MT_Element:
        {
            // Get the id array.
            vtkIntArray* idArray = vtkIntArray::SafeDownCast(cellData->GetArray(DATA_ELEM_ID_ARRAY_NAME));
            if (!idArray){
                return -1;
            }

            int nVal = idArray->GetNumberOfValues();
            if (vtkId >= nVal){
                return -1;
            }

            int dataId = idArray->GetValue(vtkId);
            return dataId;
        }
        default:
            // Return data id.
            return this->Superclass::getShapeIdByVTKCellId(vtkId, topAbsShapeType);
        }

        return -1;
    }

    void FITKAcousticsVTKGraphObjectFEFaces::init()
    {
        this->Superclass::init();

        //设置偏移量（显示层级）
        m_polygonOffset = FITKAcousticsVTKCommons::s_polygonOffsetFEFace;
    }

    bool FITKAcousticsVTKGraphObjectFEFaces::generateDataSet()
    {
        return true;
    }

    void FITKAcousticsVTKGraphObjectFEFaces::generateGraph()
    {
        this->Superclass::generateGraph();
        m_fActor->GetProperty()->SetEdgeVisibility(true);

        //初始化颜色表
        initLookUptable(m_fActor->GetMapper()->GetLookupTable());
        //更新数据对象颜色
        updateByDataColor();
    }
}